package com.wjy.game;

import java.awt.*;
import java.awt.event.*;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.util.Objects;

import javax.imageio.ImageIO;
import javax.swing.*;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Data
public class MultiClient extends View implements ActionListener, KeyListener, MouseListener {
    // 和服务器建立连接的socket
    private Socket chatSocket;
    // 发送到服务器的数据流
    private DataInputStream in;
    // 从服务器接收的数据流
    private DataOutputStream out;
    // 棋手名称
    private String chessClientName = null;
    // 对手名称
    private String chessServerName = null;
    // 默认服务器地址
    private String host = "127.0.0.1";
    // 默认服务器端口
    private int port = 5024;
    // 对弈线程
    private MessageClient thread;
    // 画布
    private  Canvas canvas = new MyCanvas();
    // 棋盘
    private int[][] chessBoard = new int[15][15];
    // 当前棋子落点
    private  Point currentChess = new Point();
    // 是否处于对弈状态
    private boolean isOnChess = false;
    // 游戏是否开始
    private boolean isOnStart = false;
    // 对手颜色
    private String peerColor = "";
    // 是否是自己的回合
    private boolean isYourTurn = false;

    public MultiClient() throws Exception {
        // 获取棋手名称
        chessClientName = this.roleNameLabel.getText();
        for (int i = 0; i < 15; i++) {
            for (int j = 0; j < 15; j++) {
                chessBoard[i][j] = -1;
            }
        }
        canvas.setSize(527, 565);
        panelLeft.add(canvas);
        // 给各个组件添加监听事件
        sendButton.addActionListener(this);
        startButton.addActionListener(this);
        createRoomButton.addActionListener(this);
        exitRoomButton.addActionListener(this);
        repentanceButton.addActionListener(this);
        joinButton.addActionListener(this);
        okButton.addActionListener(this);
        messageField.addKeyListener(this);
        canvas.addMouseListener(this);

        // 窗口事件
        frame.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                log.info("关闭窗口");
                System.exit(0);
            }

            @Override
            public void windowActivated(WindowEvent e) {

            }
        });
        // 连接服务器
        if (connectServer(host, port)) {
            JOptionPane.showMessageDialog(frame, "连接服务器成功！", "提示", 2);
        } else {
            JOptionPane.showMessageDialog(frame, "连接服务器失败！", "提示", 0);
        }

    }

    public Color getColor(String color) {
        if ("0".equals(color)) {
            return Color.black;
        } else if ("1".equals(color)) {
            return Color.white;
        } else if ("2".equals(color)) {
            return Color.red;
        } else if ("3".equals(color)) {
            return Color.green;
        } else if ("4".equals(color)) {
            return Color.blue;
        } else if ("5".equals(color)) {
            return Color.pink;
        } else if ("6".equals(color)) {
            return Color.yellow;
        } else {
            return Color.orange;
        }
    }

    /**
     * 检查是否胜利
     *
     * @return
     */
    public boolean checkwin() {
        // 获取当前棋手使用的棋子颜色
        int color = comboBox.getSelectedIndex();

        for (int i = 0; i < 15; i++) {
            for (int j = 0; j < 11; j++) {
                if (chessBoard[i][j] == color && chessBoard[i][j + 1] == color && chessBoard[i][j + 2] == color
                    && chessBoard[i][j + 3] == color && chessBoard[i][j + 4] == color) {
                    thread.sendMessage("FAIL " + chessServerName);
                    JOptionPane.showMessageDialog(frame, "恭喜你获胜了！", "提示", 1);
                    comboBox.setEnabled(true);
                    sendButton.setEnabled(false);
                    joinButton.setEnabled(true);
                    createRoomButton.setEnabled(true);
                    exitRoomButton.setEnabled(false);
                    repentanceButton.setEnabled(false);
                    for (int i1 = 0; i1 < 15; i1++) {
                        for (int j1 = 0; j1 < 15; j1++) {
                            chessBoard[i1][j1] = -1;
                        }
                    }
                    canvas.paint(canvas.getGraphics());
                    canvas.update(canvas.getGraphics());
                    isYourTurn = false;
                    isOnChess = false;
                    isOnStart = false;
                    return true;
                }
            }
        }
        for (int i = 0; i < 11; i++) {
            for (int j = 0; j < 15; j++) {
                if (chessBoard[i][j] == color && chessBoard[i + 1][j] == color && chessBoard[i + 2][j] == color
                    && chessBoard[i + 3][j] == color && chessBoard[i + 4][j] == color) {
                    thread.sendMessage("FAIL " + chessServerName);
                    JOptionPane.showMessageDialog(frame, "恭喜你获胜了！", "提示", 1);
                    comboBox.setEnabled(true);
                    sendButton.setEnabled(false);
                    joinButton.setEnabled(true);
                    createRoomButton.setEnabled(true);
                    exitRoomButton.setEnabled(false);
                    repentanceButton.setEnabled(false);
                    for (int i1 = 0; i1 < 15; i1++) {
                        for (int j1 = 0; j1 < 15; j1++) {
                            chessBoard[i1][j1] = -1;
                        }
                    }
                    canvas.paint(canvas.getGraphics());
                    canvas.update(canvas.getGraphics());
                    isYourTurn = false;
                    isOnChess = false;
                    isOnStart = false;
                    return true;
                }
            }
        }
        for (int i = 0; i < 11; i++) {
            for (int j = 0; j < 11; j++) {
                if (chessBoard[i][j] == color && chessBoard[i + 1][j + 1] == color && chessBoard[i + 2][j + 2] == color
                    && chessBoard[i + 3][j + 3] == color && chessBoard[i + 4][j + 4] == color) {
                    thread.sendMessage("FAIL " + chessServerName);
                    JOptionPane.showMessageDialog(frame, "恭喜你获胜了！", "提示", 1);
                    comboBox.setEnabled(true);
                    sendButton.setEnabled(false);
                    joinButton.setEnabled(true);
                    createRoomButton.setEnabled(true);
                    exitRoomButton.setEnabled(false);
                    repentanceButton.setEnabled(false);
                    for (int i1 = 0; i1 < 15; i1++) {
                        for (int j1 = 0; j1 < 15; j1++) {
                            chessBoard[i1][j1] = -1;
                        }
                    }
                    canvas.paint(canvas.getGraphics());
                    canvas.update(canvas.getGraphics());
                    isYourTurn = false;
                    isOnChess = false;
                    isOnStart = false;
                    return true;
                }
            }
        }
        for (int i = 4; i < 15; i++) {
            for (int j = 0; j < 11; j++) {
                if (chessBoard[i][j] == color && chessBoard[i - 1][j + 1] == color && chessBoard[i - 2][j + 2] == color
                    && chessBoard[i - 3][j + 3] == color && chessBoard[i - 4][j + 4] == color) {
                    thread.sendMessage("FAIL " + chessServerName);
                    JOptionPane.showMessageDialog(frame, "恭喜你获胜了！", "提示", 1);
                    comboBox.setEnabled(true);
                    sendButton.setEnabled(false);
                    joinButton.setEnabled(true);
                    createRoomButton.setEnabled(true);
                    exitRoomButton.setEnabled(false);
                    repentanceButton.setEnabled(false);
                    for (int i1 = 0; i1 < 15; i1++) {
                        for (int j1 = 0; j1 < 15; j1++) {
                            chessBoard[i1][j1] = -1;
                        }
                    }
                    canvas.paint(canvas.getGraphics());
                    canvas.update(canvas.getGraphics());
                    isYourTurn = false;
                    isOnChess = false;
                    isOnStart = false;
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * 保存棋子落点到数组中
     *
     * @param x
     * @param y
     * @param color
     */
    public void keepPoint(int x, int y, int color) {
        int tempX = ((x - 18) / 35);
        int tempY = ((y - 18) / 35);
        chessBoard[tempX][tempY] = color;
    }

    /**
     * 连接服务器
     *
     * @param serverIP
     * @param serverPort
     * @return
     * @throws Exception
     */
    public boolean connectServer(String serverIP, int serverPort) throws Exception {
        try {
            chatSocket = new Socket(serverIP, serverPort);
            in = new DataInputStream(chatSocket.getInputStream());
            out = new DataOutputStream(chatSocket.getOutputStream());
            MessageClient thread = new MessageClient(this);
            thread.start();
            this.thread = thread;
            thread.sendMessage("SEND_NAME " + chessClientName);
            return true;
        } catch (IOException ex) {
            messageBox.setText("连接服务器失败！");
        }
        return false;
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if (e.getSource() == createRoomButton) {
            JOptionPane.showMessageDialog(frame, "创建成功等待加入！", "提示", 2);
            messageBox.setText("创建成功等待加入！");
            sendButton.setEnabled(false);
            startButton.setEnabled(false);
            createRoomButton.setEnabled(false);
            exitRoomButton.setEnabled(true);
            repentanceButton.setEnabled(false);
            thread.sendMessage("CREATE_ROOM " + chessClientName);
        }
        // 加入房间查询房间列表
        if (e.getSource() == joinButton) {
            thread.sendMessage("LIST_ROOM");
        }
        // 退出房间，则表示弃赛认输
        if (e.getSource() == exitRoomButton) {
            if (isOnChess) {
                thread.sendMessage("GIVE_UP_IN_GAME " + chessClientName);
                createRoomButton.setEnabled(true);
                exitRoomButton.setEnabled(false);
                joinButton.setEnabled(true);
                sendButton.setEnabled(false);
                startButton.setEnabled(false);
                messageBox.setText("");
                for (int i1 = 0; i1 < 15; i1++) {
                    for (int j1 = 0; j1 < 15; j1++) {
                        chessBoard[i1][j1] = -1;
                    }
                }
                canvas.paint(canvas.getGraphics());
                canvas.update(canvas.getGraphics());
                isYourTurn = false;
                isOnChess = false;
                isOnStart = false;
            } else {
                thread.sendMessage("GIVE_UP_NO_START " + chessClientName);
                createRoomButton.setEnabled(true);
                exitRoomButton.setEnabled(false);
                joinButton.setEnabled(true);
                sendButton.setEnabled(false);
                startButton.setEnabled(false);
                messageBox.setText("");
                isOnChess = false;
                for (int i1 = 0; i1 < 15; i1++) {
                    for (int j1 = 0; j1 < 15; j1++) {
                        chessBoard[i1][j1] = -1;
                    }
                }
                canvas.paint(canvas.getGraphics());
                canvas.update(canvas.getGraphics());
                isYourTurn = false;
                isOnStart = false;
            }
        }
        if (e.getSource() == okButton) {
            int indexI = Integer.valueOf(choseTextField.getText());
            if (choseTextField.getText().equals("")) {
                JOptionPane.showMessageDialog(frame, "房间号不能为空！", "提示", 0);
            }
            if (indexI <= 0 || indexI > roomName.length) {
                JOptionPane.showMessageDialog(frame, "请输入正确的房间编号！", "提示", 0);
            } else if (1 <= indexI && indexI <= 25) {
                if (roomName[indexI - 1].endsWith("游戏中")) {
                    JOptionPane.showMessageDialog(frame, "游戏中不能加入！", "提示", 2);
                } else {
                    String peerName = roomName[indexI - 1].substring(0, roomName[indexI - 1].length() - 7);
                    if (peerName.equals(chessClientName)) {
                        JOptionPane.showMessageDialog(frame, "自己的房间无法加入！", "提示", 0);
                    } else {
                        thread.sendMessage("JOIN_ROOM " + peerName + " " + chessClientName);
                    }
                }
            }
        }
        if (e.getSource() == sendButton) {
            if (!messageField.getText().equals("")) {
                thread.sendMessage("TALK " + chessServerName + " " + messageField.getText());
                messageField.setText("");
                messageBox.setText("发送消息成功！");
            }
        }
        if (e.getSource() == startButton) {
            isOnStart = true;
            comboBox.setEnabled(false);
            startButton.setEnabled(false);
            thread.sendMessage("START_GAME " + chessClientName + " " + comboBox.getSelectedIndex());
        }
        if (e.getSource() == repentanceButton) {
            thread.sendMessage("TAKE_BACK " + chessServerName);
        }
    }

    /**
     * 计算棋子落子中心位置
     *
     * @param x
     * @return
     */
    public int roundNum(double x) {
        double temp = Math.abs(x - 18);
        if (temp / 35.00 > 0.5) {
            return 35 * (((int)temp / 35) + 1) + 18;
        } else {
            return 35 * ((int)temp / 35) + 18;
        }
    }

    @Override
    public void mouseClicked(MouseEvent e) {
        // 落子
        if (isYourTurn) {
            if (chessBoard[(roundNum(e.getX() - 11) - 18) / 35][(roundNum(e.getY() - 11) - 18) / 35] == -1) {
                currentChess.x = roundNum(e.getX() - 11);
                currentChess.y = roundNum(e.getY() - 11);
                System.out.println(currentChess);
                keepPoint(roundNum(e.getX() - 11), roundNum(e.getY() - 11), comboBox.getSelectedIndex());
                canvas.paint(canvas.getGraphics());
                canvas.update(canvas.getGraphics());
                repentanceButton.setEnabled(true);
                // 落子后检查是否获胜
                if (!checkwin()) {
                    isYourTurn = false;
                    thread.sendMessage(
                        "CHESS " + chessServerName + " " + roundNum(e.getX() - 11) + " " + roundNum(e.getY() - 11));
                }
            }
        }
    }

    @Override
    public void mousePressed(MouseEvent e) {

    }

    @Override
    public void mouseReleased(MouseEvent e) {

    }

    @Override
    public void mouseEntered(MouseEvent e) {

    }

    @Override
    public void mouseExited(MouseEvent e) {

    }

    @Override
    public void keyTyped(KeyEvent e) {

    }

    @Override
    public void keyPressed(KeyEvent e) {
        // 发送消息
        if (e.getKeyCode() == KeyEvent.VK_ENTER && sendButton.isEnabled()) {
            if (!messageField.getText().equals("")) {
                thread.sendMessage("TALK " + chessServerName + " " + messageField.getText());
                messageField.setText("");
                messageBox.setText("发送消息成功！");
            }
        }
    }

    @Override
    public void keyReleased(KeyEvent e) {

    }

    /**
     * 棋盘棋子绘制
     */
    public class MyCanvas extends Canvas {

        @Override
        public void paint(Graphics g) {
            Graphics2D g2d = (Graphics2D)g;
            int gap = 18;
            // 行间距35,顶部和底部各留18像素
            for (int i = 0; i < 15; i++) {
                g2d.drawLine(18, gap, 508, gap);
                g2d.drawLine(gap, 18, gap, 508);
                gap += 35;
            }
            // 启用抗锯齿
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            // 绘制天元等多个点位
            g2d.fillOval(18 + 35 * 3 - 5, 18 + 35 * 3 - 5, 10, 10);
            g2d.fillOval(18 + 35 * 3 - 5, 18 + 35 * 11 - 5, 10, 10);
            g2d.fillOval(18 + 35 * 7 - 5, 18 + 35 * 7 - 5, 10, 10);
            g2d.fillOval(18 + 35 * 11 - 5, 18 + 35 * 3 - 5, 10, 10);
            g2d.fillOval(18 + 35 * 11 - 5, 18 + 35 * 11 - 5, 10, 10);
            for (int i = 0; i < 15; i++) {
                for (int j = 0; j < 15; j++) {
                    if (chessBoard[i][j] != -1) {
                        int x = i * 35 + 18;
                        int y = j * 35 + 18;
                        Color chessColor = getColor(String.valueOf(chessBoard[i][j]));
                        Image chessImage = null;
                        try {
                            if (chessColor == Color.black) {
                                chessImage = ImageIO
                                    .read(Objects.requireNonNull(getClass().getClassLoader().getResource("black.png")));
                            } else {
                                chessImage = ImageIO
                                    .read(Objects.requireNonNull(getClass().getClassLoader().getResource("white.png")));
                            }
                        } catch (IOException e) {
                            throw new RuntimeException(e);
                        }
                        // g.setColor(chessColor);
                        if (currentChess.getX() == x && currentChess.getY() == y) {
                            g2d.drawImage(chessImage, currentChess.x - 11, currentChess.y - 11, 22, 22, null);
                            // g.fillOval(currentChess.x - 11, currentChess.y - 11, 22, 22);
                            // 标记当前位置
                            g2d.setColor(Color.RED);
                            g2d.drawLine(currentChess.x - 3, currentChess.y, currentChess.x + 3,
                                currentChess.y);
                            g2d.drawLine(currentChess.x, currentChess.y - 3, currentChess.x,
                                currentChess.y + 3);
                        } else {
                            g2d.drawImage(chessImage, x - 11, y - 11, 22, 22, null);
                            // g.fillOval(x - 11, y - 11, 22, 22);
                        }
                    }
                }
            }
        }
    }
}